<?php

/**
 * Aurorum - Open source digital signage
 *
 * @link http://digitalsignage.tk
 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 *
 * @category Aurorum
 * @package Aurorum
 */

/**
 * This class handles Slide requests.
 *
 * @package Aurorum
 * @subpackage Controllers
 */

class ADS_SlideController extends ADS_DefaultController{
    
    const STATUS_ADD_OK    = 1;
    const STATUS_REMOVE_OK = 3;
    const STATUS_EDIT_OK   = 5;
    
    const SLIDE_INCREASE_OK = 7;
    const SLIDE_DECREASE_OK = 9;
    
    const ITEM_ADD_OK      = 1;
    const ITEM_REMOVE_OK   = 3;
    const ITEM_EDIT_OK     = 9;
    
    const BULK_ACTION_REMOVE = 'remove';
    
    public function handleDefaultBulkAction(){
        //get variables         
        $post   =  (array)ADS_Input::postVar('post', array());
        $action = (string)_ifset(
            ADS_Input::postVar('action1', '-1') !== '-1',
            ADS_Input::postVar('action1', '-1'),
            ADS_Input::postVar('action2', '-1')
        );
        //validate token
        if(!wp_verify_nonce(ADS_Input::postVar('token', ''), $_GET['page'].':defaultBulkAction')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        //parse action
        switch ($action) {            
            case self::BULK_ACTION_REMOVE:                
                    $status = $this->bulkRemoveSlides($post);                
                break;

            default:
                //action is not recognized (do nothing)
                //throw new ADS_UnknownBulkActionException('Action is not recognized.');
                break;
        }
        //redir
        ADS_Navigator::redir('self:defaultAction',array(
            'msg' => $status
        ));
    }
    
    public function bulkRemoveSlides($slides){
        //validate parameters
        if(!is_array($slides)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        ADS_Navigator::freeze();
        foreach ($slides as $slideId) {
            $this->handleRemoveSlide((int)$slideId, false);
        }
        ADS_Navigator::unfreeze();        
    }
    
    public function handleRemoveSlide($slideId = 0, $useToken = true){
        //validate parameters
        if(!is_int($slideId) || !is_bool($useToken)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        //validate token
        if($useToken && !wp_verify_nonce(ADS_Input::getVar('token', ''), $_GET['page'].':removeSlide')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        //get variables
        $slideId = (int)_ifset($slideId > 0, $slideId, ADS_Input::getVar('slideId', 0));                
        //remove slide
        $sModel = new ADS_SlideModel();
        $slide = $sModel->getSlide($slideId);
        $sModel->removeSlide($slideId);
        //log change
        ADS_Logger::logChange('Slide "%s" was removed.', $slide['name']);
        //redir
        ADS_Navigator::redir('self:defaultAction',array(
            'msg' => self::STATUS_REMOVE_OK
        ));
    }
    
    public function handleAddSlide(){
        
        $sModel = new ADS_SlideModel();
        //default values
        $slide   = array();
        $isValid = true;
        //resolve action
        $action = ADS_Input::postVar('action', 'default');         
        switch($action){
            case 'add':
                $slide['name']      = (string)ADS_Input::postVar('slide.name', '');
                $slide['layoutId']  =    (int)ADS_Input::postVar('slide.layoutId', -1);
                $slide['validFrom'] = (string)ADS_Input::postVar('slide.validFrom', date('Y/m/d'));
                $slide['validTo']   = (string)ADS_Input::postVar('slide.validTo', date('Y/m/d')); 
                //validation
                if(!ads_checkdate($slide['validFrom']) || !ads_checkdate($slide['validTo'])){
                    ADS_MsgStack::push('error', sprintf('Wrong format of date. Must be dd/mm/yyyy.'));
                    $isValid = false;
                }
                if(mb_strlen($slide['name']) == 0){
                    ADS_MsgStack::push('error', sprintf('Name of slide can not be blank.'));
                    $isValid = false;
                }
                if(mb_strlen($slide['name']) > 0 && (mb_strlen($slide['name']) < 4 || mb_strlen($slide['name']) > 255)){
                    ADS_MsgStack::push('error', sprintf('Name of slide must be between %d and %d characters long.', 4, 255));
                    $isValid = false;
                }
                if($slide['layoutId'] === -1){
                    ADS_MsgStack::push('error', sprintf('Layout can not be blank.'));
                    $isValid = false;
                }
                
                if($isValid){
                    //insert new slide to db
                    $sModel->addSlide($slide);
                    //log change
                    ADS_Logger::logChange('Slide "%s" was inserted.', $slide['name']);
                    //redir
                    ADS_Navigator::redir('self:defaultAction',array(
                        'msg' => self::STATUS_ADD_OK
                    ));
                }                
                break;                
        }  
        //add variables to output
        ADS_Output::register('slide', $slide);
        ADS_Output::register('errors', $errors);
        ADS_Output::register('layouts', ads_prepare_options($sModel->getLayouts(), 'ID', 'post_title'));
        
    }
    
    public function handleEditSlide(){
        
        $sModel = new ADS_SlideModel();
        //default values
        $slideId = (int)ADS_Input::getVar('slideId', 0);
        $slide   = $sModel->getSlide($slideId);
        $isValid = true;
        //resolve action
        $action = ADS_Input::postVar('action', 'default');         
        switch($action){
            case 'edit':
                $slide = array();
                //get values
                $slide['name']      = (string)ADS_Input::postVar('slide.name', '');
                $slide['layoutId']  =    (int)ADS_Input::postVar('slide.layoutId', -1);
                $slide['position']  =    (int)ADS_Input::postVar('slide.position', -1);
                $slide['validFrom'] = (string)ADS_Input::postVar('slide.validFrom', date('Y/m/d'));
                $slide['validTo']   = (string)ADS_Input::postVar('slide.validTo', date('Y/m/d')); 
                //validation
                if(!ads_checkdate($slide['validFrom']) || !ads_checkdate($slide['validTo'])){
                    ADS_MsgStack::push('error', sprintf('Wrong format of date. Must be dd/mm/yyyy.'));
                    $isValid = false;
                }
                if(mb_strlen($slide['name']) == 0){
                    ADS_MsgStack::push('error', sprintf('Name of slide can not be blank.'));
                    $isValid = false;
                }
                if(mb_strlen($slide['name']) > 0 && (mb_strlen($slide['name']) < 4 || mb_strlen($slide['name']) > 255)){
                    ADS_MsgStack::push('error', sprintf('Name of slide must be between %d and %d characters long.', 4, 255));
                    $isValid = false;
                }
                if($slide['layoutId'] === -1){
                    ADS_MsgStack::push('error', sprintf('Layout can not be blank.'));
                    $isValid = false;
                }
                if($slide['position'] === -1){
                    ADS_MsgStack::push('error', sprintf('Position can not be blank.'));
                    $isValid = false;
                }
                //ready to go
                if($isValid){
                    //insert new slide to db
                    $sModel->editSlide($slideId, $slide);
                    //log change
                    ADS_Logger::logChange('Slide "%s" was updated.', $slide['name']);
                    //redir
                    ADS_Navigator::redir('self:defaultAction',array(
                        'msg' => self::STATUS_EDIT_OK
                    ));
                }                
                break;                
        }  
        //add variables to output
        ADS_Output::register('slide', $slide);
        ADS_Output::register('errors', $errors);
        ADS_Output::register('layouts', ads_prepare_options($sModel->getLayouts(), 'ID', 'post_title'));
        
    }
    
    public function handleItemBulkAction(){
        //get variables
        $post   =  (array)ADS_Input::postVar('post', array()); 
        $action = (string)_ifset(
            ADS_Input::postVar('action1', '-1') !== '-1',
            ADS_Input::postVar('action1', '-1'),
            ADS_Input::postVar('action2', '-1')
        );
        //validate token
        if(!wp_verify_nonce(ADS_Input::postVar('token', ''), $_GET['page'].':itemBulkAction')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        //parse action
        switch ($action) {            
            case self::BULK_ACTION_REMOVE:                
                    $status = $this->bulkRemoveItems($post);                
                break;

            default:
                //action is not recognized (do nothing)
                //throw new ADS_UnknownBulkActionException('Action is not recognized.');
                break;
        }
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => $status
        ), 'slideId');
    }
    
    public function bulkRemoveItems($items){        
        //validate parameters
        if(!is_array($items)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        ADS_Navigator::freeze();
        foreach ($items as $itemId) {
            $this->handleRemoveItem((int)$itemId, false);
        }
        ADS_Navigator::unfreeze();        
    }
    
    public function handleRemoveItem($itemId = 0, $useToken = true){        
        //validate parameters
        if(!is_int($itemId) || !is_bool($useToken)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        //validate token
        if($useToken && !wp_verify_nonce(ADS_Input::getVar('token', ''), $_GET['page'].':removeItem')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        $siModel = new ADS_SlideItemModel();
        //get variables        
        $itemId = (int)_ifset($itemId > 0, $itemId, ADS_Input::getVar('itemId', 0)); 
        //remove frame
        $item = $siModel->getItem($itemId);
        $siModel->removeItem($itemId);
        //log change        
        ADS_Logger::logChange('Item "%s" was removed.', $item['name']);
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => self::ITEM_REMOVE_OK
        ), 'slideId');
    }
    
    public function handleEditItems(){
        
        //default values
        $page    =    (int)ADS_Input::getVar('paged', 1);
        $orderBy = (string)ADS_Input::getVar('orderBy', 'itemId');
        $order   = (string)ADS_Input::getVar('order', 'ASC');
        $slideId =    (int)ADS_Input::getVar('slideId', 0);
        $item    = array();        
        //prepare filter
        $filter = array();
        //load sources
        $sModel  = new ADS_SlideModel();
        $siModel = new ADS_SlideItemModel();
        $dfModel = new ADS_DataFrameModel();
        //process slide
        $slide = $sModel->getSlide($slideId);
        $templateZones = ads_get_template_zones(
            get_post_meta($slide->postId, '_wp_page_template', true)            
        );
        //resolve action
        $action = ADS_Input::postVar('action', 'default');         
        //execute action
        switch ($action) {
            case 'add':
                $isValid = true;
                //values
                $item['slideId'] = $slideId;
                //get values
                $item['frameId'] =    (int)ADS_Input::postVar('item.frameId', -1);  
                $item['zoneId']  = (string)ADS_Input::postVar('item.zoneId', -1);  
                //validate
                if($siModel->isZoneOccupied($item['slideId'], $item['zoneId'])){
                    ADS_MsgStack::push('error', sprintf('Zone "%s" is already occupied.', $item['zoneId']));
                    $isValid = false;
                }
                //ready to go
                if($isValid){
                    //insert new item to timeline
                    $siModel->addItem($item);
                    //log change
                    ADS_Logger::logChange('Item "%s" was inserted.', $item['name']);
                    //redir
                    ADS_Navigator::redir('self:editItems',array(
                        'msg' => self::ITEM_ADD_OK                        
                    ), 'slideId');
                }

                break;
        }
        //prepare sorting
        $rules = ads_prepare_sorting($orderBy, $order, array(
            'name', 'position'
        ));
        //count records
        $cnt = (int)$siModel->countItems($slideId);
        //output
        ADS_Output::register('item', $item);
        //slide        
        ADS_Output::register('slide', $slide);
        ADS_Output::register(
            'pager',
            ads_prepare_paging($page, $siModel->getLimit(), $cnt)
        );
        ADS_Output::register(
            'slide_items', 
            $siModel->setSorter($rules)->setPager($page)->getItems($slideId)
        );
        $zones = ads_prepare_options(
            $dfModel->getFrames(), 'frameId', 'name'
        );
        ADS_Output::register('data_frames', $zones);

        ADS_Output::register('zones', ads_prepare_options(
            $templateZones, 'USE_ARR_KEY', 'name'
        ));
        //restore message
        $msg = (int)ADS_Input::getVar('msg', -1);
        if($msg === self::ITEM_ADD_OK){
            ADS_MsgStack::push('success', 'Slide was successfully inserted.');
        }
        if($msg === self::ITEM_REMOVE_OK){
            ADS_MsgStack::push('success', 'Slide was successfully removed.');
        }
    }
    
    public function handleDefaultAction(){
        //get variables
        $page    =    (int)ADS_Input::getVar('paged', 1);
        $orderBy = (string)ADS_Input::getVar('orderBy', 'position');
        $order   = (string)ADS_Input::getVar('order', 'ASC');
        //prepare filter
        $status = (string)ADS_Input::getVar('status_valid', '-1');
        $filter = array(
            'now' => array(
                array('validFrom <= NOW()'),
                array('validTo >= NOW()')
            ),
            'future' => array(
                array('validFrom > NOW()')
            ),
            'past' => array(
                array('validTo < NOW()')
            ),
        );
        //prepare sorting
        $rules = ads_prepare_sorting($orderBy, $order, array(
            'name', 'position', 'post_title', 'validFrom', 'validTo'
        ));        
        //load slides
        $sModel = new ADS_SlideModel();
        //count records
        $cnt = (int)$sModel->setFilter((array)@$filter[$status])->countSlides();
        ADS_Output::register(
            'slides',
            $sModel->setFilter((array)@$filter[$status])->setSorter($rules)->setPager($page)->getSlides()
        );        
        ADS_Output::register(
            'cnt',
            array(
                'all'    => $sModel->setFilter(array())->countSlides(),
                'now'    => $sModel->setFilter($filter['now'])->countSlides(),
                'future' => $sModel->setFilter($filter['future'])->countSlides(),
                'past'   => $sModel->setFilter($filter['past'])->countSlides()
            )            
        );        
        //ADS_Debug::dump(ads_prepare_paging($page, $sModel->getLimit(), $cnt));
        ADS_Output::register(
            'pager',
            ads_prepare_paging($page, $sModel->getLimit(), $cnt)
        );
        //restore message
        $msg = (int)ADS_Input::getVar('msg', -1);
        if($msg === self::STATUS_ADD_OK){
            ADS_MsgStack::push('success', 'Slide was successfully inserted.');
        }
        if($msg === self::STATUS_EDIT_OK){
            ADS_MsgStack::push('success', 'Slide was successfully updated.');
        }
        if($msg === self::STATUS_REMOVE_OK){
            ADS_MsgStack::push('success', 'Slide was successfully removed.');
        }
        if($msg === self::SLIDE_DECREASE_OK){
            ADS_MsgStack::push('success', 'Position was successfully changed.');
        }
        if($msg === self::SLIDE_INCREASE_OK){            
            ADS_MsgStack::push('success', 'Position was successfully changed.');
        }
    }
    
    public function handleIncreaseSlidePosition(){ 
        $slideId = (int)ADS_Input::getVar('slideId', 0);
        //increase position
        $sModel = new ADS_SlideModel();
        $sModel->increaseSlidePosition($slideId);
        //log change
        $slide = $sModel->getSlide($slideId);
        ADS_Logger::logChange('Position of slide "%s" was changed.', $slide['name']);
        //redir
        ADS_Navigator::redir('self:defaultAction',array(
            'msg' => self::SLIDE_INCREASE_OK
        ));
    }
    
    public function handleDecreaseSlidePosition(){ 
        $slideId = (int)ADS_Input::getVar('slideId', 0);
        //decrease position
        $sModel = new ADS_SlideModel();
        $sModel->decreaseSlidePosition($slideId);
        //log change
        $slide = $sModel->getSlide($slideId);
        ADS_Logger::logChange('Position of slide "%s" was changed.', $slide['name']);
        //redir
        ADS_Navigator::redir('self:defaultAction',array(
            'msg' => self::SLIDE_DECREASE_OK
        ));
    }  
    
}